package com.ug.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author LY
 * @create 2024/7/16 16:56
 * @Description 上下文工具类
 */
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {

    private static final Logger logger = LoggerFactory.getLogger(SpringContextHolder.class);

    private static ApplicationContext applicationContext = null;

    private static final List<CallBack> CALL_BACKS = new ArrayList<>();

    private static boolean addCallback = true;

    /**
     * 从applicationContext中获取Bean并自动转化为所赋值对象的类型
     * @param requiredType 目标类
     */
    public static <T> T getBean(Class<T> requiredType){
        assertContextInjected();
        return applicationContext.getBean(requiredType);
    }

    /**
     * 从applicationContext中获取Bean并自动转化为所赋值对象的类型
     * @param beanName bean名称
     */
    public static Object getBean(String beanName){
        assertContextInjected();
        return applicationContext.getBean(beanName);
    }

    /**
     * 校验ApplicationContext
     */
    private static void assertContextInjected(){
        if (applicationContext == null){
            throw new IllegalStateException("applicationContext属性未注入，" +
                    "请在SpringBoot启动类中注册SpringContextHolder.");
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringContextHolder.applicationContext != null){
            logger.info("SpringContextHolder中的ApplicationContext被覆盖，" +
                    "原ApplicationContext为：" + SpringContextHolder.applicationContext);
        }
        SpringContextHolder.applicationContext = applicationContext;
        if (addCallback){
            for (CallBack callBack : SpringContextHolder.CALL_BACKS) {
                callBack.executor();
            }
        }
        SpringContextHolder.addCallback = false;
    }

    @Override
    public void destroy() {
        logger.info("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
        applicationContext = null;
    }
}
